package ljl.bilibili.gateway.filter;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtException;
import ljl.bilibili.gateway.constant.Constant;
import ljl.bilibili.gateway.util.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpCookie;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextImpl;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;

import java.util.Collections;

import static ljl.bilibili.gateway.constant.Constant.*;

@Slf4j
public class JwtAuthorizationFilter implements WebFilter {

    /**
     *打印请求路径，用自定义请求头隔绝csrf攻击，取出token认证用户与验证权限
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        String path = exchange.getRequest().getURI().getPath();
        //跟踪请求路径
        if (!path.contains("webjars") && !path.contains("swagger") && !path.contains("api")) {
            log.info(exchange.getRequest().getURI().getPath());
        }
        String jwt = exchange.getRequest().getHeaders().getFirst(Constant.SHORT_TOKEN);
        HttpCookie cookie = exchange.getRequest().getCookies().getFirst(LONG_TOKEN);
        String aigcBiliBiliHeader = exchange.getRequest().getHeaders().getFirst(Constant.SAFE_REQUEST_HEADER);
        //如果没有该请求头则是非网站源发起的请求
        if (aigcBiliBiliHeader == null) {
            exchange.getResponse().setStatusCode(HttpStatus.BAD_REQUEST);
            return exchange.getResponse().setComplete();
        }
//        如果token不为空则设置权限到security上下文中
        if (jwt != null && !jwt.isEmpty()) {
            // 如果短token过期
            if (!JwtUtil.validateToken(jwt)) {
                // 如果长token未过期，刷新短token
//                if (cookie != null){
//                    String longToken = cookie.getValue();
//                    jwt = JwtUtil.refreshToken(longToken,1);
//                } else {
                    return chain.filter(exchange);
//                }
            }
            Claims claims = JwtUtil.getClaimsFromToken(jwt);
            String role = claims.get(JWT_ROLE, String.class);
            Integer userId = claims.get(USERIDENTITY, Integer.class);
            SimpleGrantedAuthority authority = new SimpleGrantedAuthority(JWT_ROLE + ":" + role);
            Authentication authentication = new UsernamePasswordAuthenticationToken(
                    userId,
                    null,
                    Collections.singletonList(authority)
            );
//            SecurityContext context = new SecurityContextImpl();
//            context.setAuthentication(authentication);

            SecurityContextHolder.getContext().setAuthentication(authentication);
//            Authentication auth = SecurityContextHolder.getContext().getAuthentication();
//            Integer loginUser = (Integer) auth.getPrincipal();
//            log.warn("登录用户是：" + loginUser);

            return chain.filter(exchange)
                    .contextWrite(ReactiveSecurityContextHolder.withSecurityContext(Mono.just(SecurityContextHolder.getContext())));
        }
//        为空则返回401，需要登录
        else {
            return chain.filter(exchange);
        }
    }
}